/*******************************************************************************
 * Copyright (c) 2007 Pascal Essiembre.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Pascal Essiembre - initial API and implementation
 ******************************************************************************/
package org.eclipse.babel.editor.preferences;

import org.eclipse.babel.editor.plugin.MessagesEditorPlugin;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * Plugin formatting preference page.
 * 
 * @author Pascal Essiembre (pascal@essiembre.com)
 */
public class FormattingPrefPage extends AbstractPrefPage {

    /* Preference fields. */
    private Button showGeneratedBy;

    private Button convertUnicodeToEncoded;
    private Button convertUnicodeUpperCase;

    private Button alignEqualSigns;
    private Button ensureSpacesAroundEquals;

    private Button groupKeys;
    private Text groupLevelDeep;
    private Text groupLineBreaks;
    private Button groupAlignEqualSigns;

    private Button wrapLines;
    private Text wrapCharLimit;
    private Button wrapAlignEqualSigns;
    private Text wrapIndentSpaces;
    private Button wrapNewLine;

    private Button newLineTypeForce;
    private Button[] newLineTypes = new Button[3];

    private Button keepEmptyFields;
    private Button sortKeys;

    /**
     * Constructor.
     */
    public FormattingPrefPage() {
        super();
    }

    /**
     * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
     */
    protected Control createContents(Composite parent) {
        IPreferenceStore prefs = getPreferenceStore();
        Composite field = null;
        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayout(new GridLayout(1, false));

        // Show generated by comment?
        field = createFieldComposite(composite);
        showGeneratedBy = new Button(field, SWT.CHECK);
        showGeneratedBy.setSelection(prefs
                .getBoolean(MsgEditorPreferences.SHOW_SUPPORT_ENABLED));
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.showGeneratedBy")); //$NON-NLS-1$

        // Convert unicode to encoded?
        field = createFieldComposite(composite);
        convertUnicodeToEncoded = new Button(field, SWT.CHECK);
        convertUnicodeToEncoded.setSelection(prefs
                .getBoolean(MsgEditorPreferences.UNICODE_ESCAPE_ENABLED));
        convertUnicodeToEncoded.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                refreshEnabledStatuses();
            }
        });
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.convertUnicode")); //$NON-NLS-1$

        // Use upper case for encoded hexadecimal values?
        field = createFieldComposite(composite, indentPixels);
        convertUnicodeUpperCase = new Button(field, SWT.CHECK);
        convertUnicodeUpperCase.setSelection(prefs
                .getBoolean(MsgEditorPreferences.UNICODE_ESCAPE_UPPERCASE));
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.convertUnicode.upper"));//$NON-NLS-1$

        // Align equal signs?
        field = createFieldComposite(composite);
        alignEqualSigns = new Button(field, SWT.CHECK);
        alignEqualSigns.setSelection(prefs
                .getBoolean(MsgEditorPreferences.ALIGN_EQUALS_ENABLED));
        alignEqualSigns.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                refreshEnabledStatuses();
            }
        });
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.alignEquals")); //$NON-NLS-1$

        field = createFieldComposite(composite);
        ensureSpacesAroundEquals = new Button(field, SWT.CHECK);
        ensureSpacesAroundEquals.setSelection(prefs
                .getBoolean(MsgEditorPreferences.SPACES_AROUND_EQUALS_ENABLED));
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.spacesAroundEquals")); //$NON-NLS-1$

        // Group keys?
        field = createFieldComposite(composite);
        groupKeys = new Button(field, SWT.CHECK);
        groupKeys.setSelection(prefs
                .getBoolean(MsgEditorPreferences.GROUP_KEYS_ENABLED));
        groupKeys.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                refreshEnabledStatuses();
            }
        });
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.groupKeys")); //$NON-NLS-1$

        // Group keys by how many level deep?
        field = createFieldComposite(composite, indentPixels);
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.levelDeep")); //$NON-NLS-1$
        groupLevelDeep = new Text(field, SWT.BORDER);
        groupLevelDeep.setText(prefs
                .getString(MsgEditorPreferences.GROUP_LEVEL_DEEP));
        groupLevelDeep.setTextLimit(2);
        setWidthInChars(groupLevelDeep, 2);
        groupLevelDeep.addKeyListener(new IntTextValidatorKeyListener(
                MessagesEditorPlugin.getString("prefs.levelDeep.error"))); //$NON-NLS-1$

        // How many lines between groups?
        field = createFieldComposite(composite, indentPixels);
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.linesBetween")); //$NON-NLS-1$
        groupLineBreaks = new Text(field, SWT.BORDER);
        groupLineBreaks.setText(prefs
                .getString(MsgEditorPreferences.GROUP_SEP_BLANK_LINE_COUNT));
        groupLineBreaks.setTextLimit(2);
        setWidthInChars(groupLineBreaks, 2);
        groupLineBreaks.addKeyListener(new IntTextValidatorKeyListener(
                MessagesEditorPlugin.getString("prefs.linesBetween.error"))); //$NON-NLS-1$

        // Align equal signs within groups?
        field = createFieldComposite(composite, indentPixels);
        groupAlignEqualSigns = new Button(field, SWT.CHECK);
        groupAlignEqualSigns.setSelection(prefs
                .getBoolean(MsgEditorPreferences.GROUP_ALIGN_EQUALS_ENABLED));
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.groupAlignEquals")); //$NON-NLS-1$

        // Wrap lines?
        field = createFieldComposite(composite);
        wrapLines = new Button(field, SWT.CHECK);
        wrapLines.setSelection(prefs
                .getBoolean(MsgEditorPreferences.WRAP_LINES_ENABLED));
        wrapLines.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                refreshEnabledStatuses();
            }
        });
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.wrapLines")); //$NON-NLS-1$

        // After how many characters should we wrap?
        field = createFieldComposite(composite, indentPixels);
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.wrapLinesChar")); //$NON-NLS-1$
        wrapCharLimit = new Text(field, SWT.BORDER);
        wrapCharLimit.setText(prefs
                .getString(MsgEditorPreferences.WRAP_LINE_LENGTH));
        wrapCharLimit.setTextLimit(4);
        setWidthInChars(wrapCharLimit, 4);
        wrapCharLimit.addKeyListener(new IntTextValidatorKeyListener(
                MessagesEditorPlugin.getString("prefs.wrapLinesChar.error"))); //$NON-NLS-1$

        // Align wrapped lines with equal signs?
        field = createFieldComposite(composite, indentPixels);
        wrapAlignEqualSigns = new Button(field, SWT.CHECK);
        wrapAlignEqualSigns.setSelection(prefs
                .getBoolean(MsgEditorPreferences.WRAP_ALIGN_EQUALS_ENABLED));
        wrapAlignEqualSigns.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                refreshEnabledStatuses();
            }
        });
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.wrapAlignEquals")); //$NON-NLS-1$

        // How many spaces/tabs to use for indenting?
        field = createFieldComposite(composite, indentPixels);
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.wrapIndent")); //$NON-NLS-1$
        wrapIndentSpaces = new Text(field, SWT.BORDER);
        wrapIndentSpaces.setText(prefs
                .getString(MsgEditorPreferences.WRAP_INDENT_LENGTH));
        wrapIndentSpaces.setTextLimit(2);
        setWidthInChars(wrapIndentSpaces, 2);
        wrapIndentSpaces.addKeyListener(new IntTextValidatorKeyListener(
                MessagesEditorPlugin.getString("prefs.wrapIndent.error"))); //$NON-NLS-1$

        // Should we wrap after new line characters
        field = createFieldComposite(composite);
        wrapNewLine = new Button(field, SWT.CHECK);
        wrapNewLine.setSelection(prefs
                .getBoolean(MsgEditorPreferences.NEW_LINE_NICE));
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.newline.nice")); //$NON-NLS-1$

        // How should new lines appear in properties file
        field = createFieldComposite(composite);
        newLineTypeForce = new Button(field, SWT.CHECK);
        newLineTypeForce.setSelection(prefs
                .getBoolean(MsgEditorPreferences.FORCE_NEW_LINE_TYPE));
        newLineTypeForce.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                refreshEnabledStatuses();
            }
        });
        Composite newLineRadioGroup = new Composite(field, SWT.NONE);
        new Label(newLineRadioGroup, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.newline.force")); //$NON-NLS-1$
        newLineRadioGroup.setLayout(new RowLayout());
        newLineTypes[0] = new Button(newLineRadioGroup, SWT.RADIO);
        newLineTypes[0].setText("UNIX (\\n)"); //$NON-NLS-1$
        newLineTypes[1] = new Button(newLineRadioGroup, SWT.RADIO);
        newLineTypes[1].setText("Windows (\\r\\n)"); //$NON-NLS-1$
        newLineTypes[2] = new Button(newLineRadioGroup, SWT.RADIO);
        newLineTypes[2].setText("Mac (\\r)"); //$NON-NLS-1$
        newLineTypes[prefs.getInt(MsgEditorPreferences.NEW_LINE_STYLE) - 1]
                .setSelection(true);

        // Keep empty fields?
        field = createFieldComposite(composite);
        keepEmptyFields = new Button(field, SWT.CHECK);
        keepEmptyFields.setSelection(prefs
                .getBoolean(MsgEditorPreferences.KEEP_EMPTY_FIELDS));
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.keepEmptyFields"));//$NON-NLS-1$

        // Sort keys?
        field = createFieldComposite(composite);
        sortKeys = new Button(field, SWT.CHECK);
        sortKeys.setSelection(prefs.getBoolean(MsgEditorPreferences.SORT_KEYS));
        new Label(field, SWT.NONE).setText(MessagesEditorPlugin
                .getString("prefs.keysSorted"));//$NON-NLS-1$

        refreshEnabledStatuses();

        return composite;
    }

    /**
     * @see org.eclipse.jface.preference.IPreferencePage#performOk()
     */
    public boolean performOk() {
        IPreferenceStore prefs = getPreferenceStore();
        prefs.setValue(MsgEditorPreferences.SHOW_SUPPORT_ENABLED,
                showGeneratedBy.getSelection());
        prefs.setValue(MsgEditorPreferences.UNICODE_ESCAPE_ENABLED,
                convertUnicodeToEncoded.getSelection());
        prefs.setValue(MsgEditorPreferences.UNICODE_ESCAPE_UPPERCASE,
                convertUnicodeUpperCase.getSelection());
        prefs.setValue(MsgEditorPreferences.ALIGN_EQUALS_ENABLED,
                alignEqualSigns.getSelection());
        prefs.setValue(MsgEditorPreferences.SPACES_AROUND_EQUALS_ENABLED,
                ensureSpacesAroundEquals.getSelection());
        prefs.setValue(MsgEditorPreferences.GROUP_KEYS_ENABLED,
                groupKeys.getSelection());
        prefs.setValue(MsgEditorPreferences.GROUP_LEVEL_DEEP,
                groupLevelDeep.getText());
        prefs.setValue(MsgEditorPreferences.GROUP_SEP_BLANK_LINE_COUNT,
                groupLineBreaks.getText());
        prefs.setValue(MsgEditorPreferences.GROUP_ALIGN_EQUALS_ENABLED,
                groupAlignEqualSigns.getSelection());
        prefs.setValue(MsgEditorPreferences.WRAP_LINES_ENABLED,
                wrapLines.getSelection());
        prefs.setValue(MsgEditorPreferences.WRAP_LINE_LENGTH,
                wrapCharLimit.getText());
        prefs.setValue(MsgEditorPreferences.WRAP_ALIGN_EQUALS_ENABLED,
                wrapAlignEqualSigns.getSelection());
        prefs.setValue(MsgEditorPreferences.WRAP_INDENT_LENGTH,
                wrapIndentSpaces.getText());
        prefs.setValue(MsgEditorPreferences.NEW_LINE_NICE,
                wrapNewLine.getSelection());
        prefs.setValue(MsgEditorPreferences.FORCE_NEW_LINE_TYPE,
                newLineTypeForce.getSelection());
        for (int i = 0; i < newLineTypes.length; i++) {
            if (newLineTypes[i].getSelection()) {
                prefs.setValue(MsgEditorPreferences.NEW_LINE_STYLE, i + 1);
            }
        }
        prefs.setValue(MsgEditorPreferences.KEEP_EMPTY_FIELDS,
                keepEmptyFields.getSelection());
        prefs.setValue(MsgEditorPreferences.SORT_KEYS, sortKeys.getSelection());
        refreshEnabledStatuses();
        return super.performOk();
    }

    /**
     * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
     */
    protected void performDefaults() {
        IPreferenceStore prefs = getPreferenceStore();
        showGeneratedBy.setSelection(prefs
                .getDefaultBoolean(MsgEditorPreferences.SHOW_SUPPORT_ENABLED));
        convertUnicodeToEncoded
                .setSelection(prefs
                        .getDefaultBoolean(MsgEditorPreferences.UNICODE_ESCAPE_ENABLED));
        convertUnicodeToEncoded
                .setSelection(prefs
                        .getDefaultBoolean(MsgEditorPreferences.UNICODE_ESCAPE_UPPERCASE));
        alignEqualSigns.setSelection(prefs
                .getDefaultBoolean(MsgEditorPreferences.ALIGN_EQUALS_ENABLED));
        alignEqualSigns
                .setSelection(prefs
                        .getDefaultBoolean(MsgEditorPreferences.SPACES_AROUND_EQUALS_ENABLED));
        groupKeys.setSelection(prefs
                .getDefaultBoolean(MsgEditorPreferences.GROUP_KEYS_ENABLED));
        groupLevelDeep.setText(prefs
                .getDefaultString(MsgEditorPreferences.GROUP_LEVEL_DEEP));
        groupLineBreaks
                .setText(prefs
                        .getDefaultString(MsgEditorPreferences.GROUP_SEP_BLANK_LINE_COUNT));
        groupAlignEqualSigns
                .setSelection(prefs
                        .getDefaultBoolean(MsgEditorPreferences.GROUP_ALIGN_EQUALS_ENABLED));
        wrapLines.setSelection(prefs
                .getDefaultBoolean(MsgEditorPreferences.WRAP_LINES_ENABLED));
        wrapCharLimit.setText(prefs
                .getDefaultString(MsgEditorPreferences.WRAP_LINE_LENGTH));
        wrapAlignEqualSigns
                .setSelection(prefs
                        .getDefaultBoolean(MsgEditorPreferences.WRAP_ALIGN_EQUALS_ENABLED));
        wrapIndentSpaces.setText(prefs
                .getDefaultString(MsgEditorPreferences.WRAP_INDENT_LENGTH));
        wrapNewLine.setSelection(prefs
                .getDefaultBoolean(MsgEditorPreferences.NEW_LINE_NICE));
        newLineTypeForce.setSelection(prefs
                .getDefaultBoolean(MsgEditorPreferences.FORCE_NEW_LINE_TYPE));
        newLineTypes[Math
                .min(prefs.getDefaultInt(MsgEditorPreferences.NEW_LINE_STYLE) - 1,
                        0)].setSelection(true);
        keepEmptyFields.setSelection(prefs
                .getDefaultBoolean(MsgEditorPreferences.KEEP_EMPTY_FIELDS));
        sortKeys.setSelection(prefs
                .getDefaultBoolean(MsgEditorPreferences.SORT_KEYS));
        refreshEnabledStatuses();
        super.performDefaults();
    }

    /* default */void refreshEnabledStatuses() {
        boolean isEncodingUnicode = convertUnicodeToEncoded.getSelection();
        boolean isGroupKeyEnabled = groupKeys.getSelection();
        boolean isAlignEqualsEnabled = alignEqualSigns.getSelection();
        boolean isWrapEnabled = wrapLines.getSelection();
        boolean isWrapAlignEqualsEnabled = wrapAlignEqualSigns.getSelection();
        boolean isNewLineStyleForced = newLineTypeForce.getSelection();

        convertUnicodeUpperCase.setEnabled(isEncodingUnicode);
        groupLevelDeep.setEnabled(isGroupKeyEnabled);
        groupLineBreaks.setEnabled(isGroupKeyEnabled);
        groupAlignEqualSigns.setEnabled(isGroupKeyEnabled
                && isAlignEqualsEnabled);
        wrapCharLimit.setEnabled(isWrapEnabled);
        wrapAlignEqualSigns.setEnabled(isWrapEnabled);
        wrapIndentSpaces.setEnabled(isWrapEnabled && !isWrapAlignEqualsEnabled);
        for (int i = 0; i < newLineTypes.length; i++) {
            newLineTypes[i].setEnabled(isNewLineStyleForced);
        }
    }

}
